using Cysharp.Threading.Tasks;
using DG.Tweening;
using IQIGame.Onigao.Framework;
using System;
using UnityEngine;
using UnityEngine.UI;

namespace IQIGame.Onigao.Game
{
    public abstract class UIBaseNode : IDisposable
    {
        private bool _ShowCalled;
        private UIAssetHelper _uiAssetHelper = null;
        private UIChildeNodeHelper _uiChildNodeHelper = null;
        private UIListHelper _uiListHelper = null;
        private UIBaseNode _rootNode = null;

        public bool isActive { get; private set; }
        public bool isDisposed { get; protected set; } = false;
        public GameObject gameObject { get; protected set; }
        public RectTransform transform { get; protected set; }
        public bool isUpdate { get; set; } = false;
        public bool isLateUpdate { get; set; } = false;
        protected ObjectBinding csObjBind { get; private set; }
        public UIBaseWindow belongWindow => this._rootNode as UIBaseWindow;
        public virtual ResLoader resLoader => this.belongWindow.resLoader;
        public UIBaseNode parentNode { get; private set; }
        protected virtual IUIGlobalEventController _msgDispatcher { get; set; }
        private UIAssetHelper uiAssetHelper
        {
            get
            {
                if (_uiAssetHelper == null)
                    _uiAssetHelper = new UIAssetHelper(this.resLoader);
                return _uiAssetHelper;
            }
        }

        private UIChildeNodeHelper uiChildNodeHelper
        {
            get
            {
                if (_uiChildNodeHelper == null)
                    _uiChildNodeHelper = new UIChildeNodeHelper(this.belongWindow, this);
                return _uiChildNodeHelper;
            }
        }

        private UIListHelper uiListHelper
        {
            get
            {
                if (_uiListHelper == null)
                    _uiListHelper = new UIListHelper(this.belongWindow, this);
                return _uiListHelper;
            }
        }

        public virtual void Init(GameObject gameObject, UIBaseNode root = null, UIBaseNode parent = null)
        {
            this._rootNode = root;
            this.parentNode = parent;
            this._ShowCalled = false;
            this._msgDispatcher = UIGlobalEventControllerFactory.Create();
            this.InitDisplay(gameObject);
            this.BeforeInit();
            this.OnInit();
            this.AddUGUIListener();
        }

        /// <summary>
        /// 初始化显示对象
        /// </summary>
        protected virtual void InitDisplay(GameObject go)
        {
            this.gameObject = go;
            this.transform = go.transform as RectTransform;
            this.isActive = go.activeSelf;
            this.csObjBind = go.GetComponent<ObjectBinding>();
        }

        /// <summary>
        /// 一般用来绑定生成组件的代码
        /// </summary>
        protected abstract void BeforeInit();

        protected abstract void OnInit();

        public virtual void Dispose()
        {
            this.isDisposed = true;
            //销毁时不需要调用Hide()，节省性能，但需判断：如果调用了Show，但每调用Hide，需要确保OnHide被调用一次，保证OnShow和OnHide成对
            if (_ShowCalled)
            {
                OnHide();
                _ShowCalled = false;
            }
            if (_uiAssetHelper != null)
            {
                _uiAssetHelper.Clear();
                _uiAssetHelper = null;
            }
            if (_uiListHelper != null)
            {
                _uiListHelper.Clear();
                _uiListHelper = null;
            }
            if (_uiChildNodeHelper != null)
            {
                _uiChildNodeHelper.Clear();
                _uiChildNodeHelper = null;
            }
            UIGlobalEventControllerFactory.Release(_msgDispatcher);
            _msgDispatcher = null;
            this.OnDispose();
            this.OnDisposeEnd();
        }

        protected abstract void OnDispose();

        private void OnDisposeEnd()
        {
            this.isActive = false;
            if (this.gameObject != null)
            {
                this.gameObject.transform.DOKill();
                UnityEngine.Object.Destroy(this.gameObject);
                this.gameObject = null;
            }
            this.transform = null;
            this.csObjBind = null;

            this._rootNode = null;
            this.parentNode = null;
        }

        /// <summary>
        /// 设置显隐
        /// </summary>
        /// <param name="isActive"></param>
        /// <returns>操作状态[true 成功 , false失败]</returns>
        protected bool SetActive(bool isActive)
        {
            if (this.isActive != isActive)
            {
                this.isActive = isActive;
                this.gameObject.SetActive(isActive);
                return true;
            }
            return false;
        }

        public void Show()
        {
            if (SetActive(true))
            {
                AddMsgListeners();
                _ShowCalled = true;
                OnShow();
            }
        }

        protected abstract void OnShow();

        public virtual void Hide()
        {
            if (SetActive(false))
            {
                OnHide();
                _msgDispatcher.Clear();
                _ShowCalled = false;
            }
        }

        protected abstract void OnHide();

        public void Update(float dt, float unscaledDt)
        {
            if (this.isActive)
            {
                this.OnUpdate(dt, unscaledDt);
                _uiChildNodeHelper?.Update(dt, unscaledDt);
            }
        }

        protected virtual void OnUpdate(float dt, float unscaledDt)
        {
        }

        public void LateUpdate()
        {
            if (this.isActive)
            {
                this.OnLateUpdate();
                _uiChildNodeHelper?.LateUpdate();
            }
        }

        protected virtual void OnLateUpdate()
        {
        }

        protected virtual void AddUGUIListener()
        {

        }

        protected virtual void AddMsgListeners()
        {
        }

        public void SetGObjName(string name)
        {
            if (this.gameObject)
                this.gameObject.name = name;
        }

        protected void SetImageSprite(Image img, string spriteAssetPath)
        {
            uiAssetHelper.SetImageSprite(img, spriteAssetPath);
        }

        protected void SetRawImageTexture(RawImage img, string textureAssetPath)
        {
            uiAssetHelper.SetRawImageTexture(img, textureAssetPath);
        }

        #region 列表 or 对象池
        protected UIItemPool<T> InitPool<T>(GameObject gobj) where T : UIBaseNode, new()
        {
            return uiListHelper.InitPool<T>(gobj);
        }

        /// <summary>
        /// 列表或者滚动的非循环列表
        /// </summary>
        protected ListScrollAdapter<T> InitListScroll<T>(GameObject gobj, System.Action<T, int> funcUnitChanged = null) where T : UIBaseNode, new()
        {
            return uiListHelper.InitListScroll<T>(gobj, funcUnitChanged);
        }

        /// <summary>
        /// 滚动的循环列表
        /// </summary>
        protected LoopScrollAdapter<T> InitLoopScroll<T>(IExLoopScrollRect scrollRect, System.Action<T, int> funcUnitChanged = null) where T : UIBaseNode, new()
        {
            return uiListHelper.InitLoopScroll<T>(scrollRect, funcUnitChanged); ;
        }

        /// <summary>
        /// 不动态创建子元素的列表(无规则布局的列表)
        /// </summary>
        protected IrregularListAdapter<T> InitIrregularList<T>(GameObject gobjRoot, System.Action<T, int> funcUnitChanged = null) where T : UIBaseNode, new()
        {
            return uiListHelper.InitIrregularList<T>(gobjRoot, funcUnitChanged);
        }
        #endregion

        #region UI的子元素对象

        protected T InitChildNode<T>(GameObject node) where T : UIBaseNode, new()
        {
            return uiChildNodeHelper.InitNode<T>(node);
        }

        protected async UniTask<T> InitChildNodeAsync<T>(string nodeAssetPath, Transform nodeParent = null) where T : UIBaseNode, new()
        {
            return await uiChildNodeHelper.InitNodeAsync<T>(nodeAssetPath, nodeParent);
        }
        #endregion

        protected void OpenUI<T>(UIBaseData uData = null) where T : UIBaseWindow, new()
        {
            ManagerCenter.UI.ShowWindow<T>(uData);
        }

        protected UniTask OpenUIAsync<T>(UIBaseData uData = null) where T : UIBaseWindow, new()
        {
            return ManagerCenter.UI.ShowWindowAsync<T>(uData);
        }

        public virtual void Close()
        {
            ManagerCenter.UI.CloseWindow(this.belongWindow, true);
        }
    }

}
